﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Windows;

namespace HAContourF
{
    /// <summary>
    /// LevelLine contains all data for one isoline line - its start point, other points and value in field.
    /// </summary>
    public sealed class LevelLine
    {
        /// <summary>
        /// Gets or sets the value of line in limits of [0..1].
        /// </summary>
        /// <value>The value01.</value>
        public double Value01 { get; set; }
        /// <summary>
        /// Gets or sets the real value of line - without scaling to [0..1] segment.
        /// </summary>
        /// <value>The real value.</value>
        public double RealValue { get; set; }

        /// <summary>
        /// Gets or sets the start point of line.
        /// </summary>
        /// <value>The start point.</value>
        public Point StartPoint { get; set; }

        private readonly List<Point> otherPoints = new List<Point>();
        /// <summary>
        /// Gets other points of line, except first point.
        /// </summary>
        /// <value>The other points.</value>
        public List<Point> OtherPoints
        {
            get { return otherPoints; }
        }

        /// <summary>
        /// Gets all points of line, including start point.
        /// </summary>
        /// <value>All points.</value>
        public IEnumerable<Point> AllPoints
        {
            get
            {
                yield return StartPoint;
                for (int i = 0; i < otherPoints.Count; i++)
                {
                    yield return otherPoints[i];
                }
            }
        }

        /// <summary>
        /// Gets all the segments of lines.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Range<Point>> GetSegments()
        {
            if (otherPoints.Count < 1)
                yield break;

            yield return new Range<Point>(StartPoint, otherPoints[0]);
            for (int i = 1; i < otherPoints.Count; i++)
            {
                yield return new Range<Point>(otherPoints[i - 1], otherPoints[i]);
            }
        }
    }

    /// <summary>
    /// IsolineTextLabel contains information about one label in isoline - its text, position and rotation.
    /// </summary>
    public sealed class IsolineTextLabel
    {
        /// <summary>
        /// Gets or sets the rotation of isoline text label.
        /// </summary>
        /// <value>The rotation.</value>
        public double Rotation { get; internal set; }
        /// <summary>
        /// Gets or sets the text of isoline label.
        /// </summary>
        /// <value>The text.</value>
        public string Text { get; internal set; }
        /// <summary>
        /// Gets or sets the position of isoline text label.
        /// </summary>
        /// <value>The position.</value>
        public Point Position { get; internal set; }
    }

    /// <summary>
    /// Collection which contains all data generated by <seealso cref="IsolineBuilder"/>.
    /// </summary>
    public sealed class IsolineCollection
    {
        private readonly List<LevelLine> lines = new List<LevelLine>();
        /// <summary>
        /// Gets the list of isoline lines.
        /// </summary>
        /// <value>The lines.</value>
        public List<LevelLine> Lines
        {
            get { return lines; }
        }

        internal void StartLine(Point p, double value01, double realValue)
        {
            LevelLine segment = new LevelLine { StartPoint = p, Value01 = value01, RealValue = realValue };
            lines.Add(segment);
        }

        internal void AddPoint(Point p)
        {
            lines[lines.Count - 1].OtherPoints.Add(p);
        }
    }
}
